/*
 * Copyright (c) 2022 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>
#include <string.h>

#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "device_resource_if.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "gpio_if.h"
#include "osal_time.h"

#include "i2c_if.h"
#include "hdf_log.h"

#define BM_E53_IIC_CHANNEL_NUM 1

static DevHandle i2cHandler = NULL;

typedef enum
{
    E53_Ok = 0,
    E53_Failed,
} E53_Status;

typedef struct
{
    // I2C设备地址
    uint16_t addr;
    //数据地址
    uint8_t *buf;
    //数据长度
    uint16_t len;
    // I2C模式
    uint16_t flags;

} E53_IIC_Msg;

typedef enum
{
    E53_I2C_FLAG_READ = (0x1 << 0),
    /** 10-bit addressing flag. The value <b>1</b> indicates that a 10-bit address is used. */
    E53_I2C_FLAG_ADDR_10BIT = (0x1 << 4),
    /** Non-ACK read flag. The value <b>1</b> indicates that no ACK signal is sent during the read process. */
    E53_I2C_FLAG_READ_NO_ACK = (0x1 << 11),
    /** Ignoring no-ACK flag. The value <b>1</b> indicates that the non-ACK signal is ignored. */
    E53_I2C_FLAG_IGNORE_NO_ACK = (0x1 << 12),
    /**
     * No START condition flag. The value <b>1</b> indicates that there is no START condition for the message
     * transfer.
     */
    E53_I2C_FLAG_NO_START = (0x1 << 14),
    /** STOP condition flag. The value <b>1</b> indicates that the current transfer ends with a STOP condition. */
    E53_I2C_FLAG_STOP = (0x1 << 15),
} E53_IIC_Flag;

E53_Status E53_IICOpen()
{

    if (i2cHandler != NULL)
    {
        E53_Log("I2C has opened,please don't open again!");
        return E53_Failed;
    }
    i2cHandler = I2cOpen(BM_E53_IIC_CHANNEL_NUM);
    if (i2cHandler == NULL)
    {
        E53_Log("I2C open failed!");
        return E53_Failed;
    }
    return E53_Ok;
}

E53_Status E53_IICClose()
{
    if (i2cHandler == NULL)
    {
        E53_Log("I2C is closed,please don't close again!");
        return E53_Failed;
    }
    I2cClose(i2cHandler);
    i2cHandler = NULL;
    return E53_Ok;
}

E53_Status E53_IICTransmit(E53_IIC_Msg *msgs, int16_t count)
{
    if (i2cHandler == NULL) //验证I2C是否开启
    {
        E53_Log("I2C didn't open!");
        return E53_Failed;
    }
    if (I2cTransfer(i2cHandler, (struct I2cMsg *)msgs, count) != count) // I2C操作函数，并验证是否成功
    {
        E53_Log("I2c read error!");
        return E53_Failed;
    }
    return E53_Ok;
}

E53_Status E53_IICWrite(uint32_t addr, uint8_t *data, uint32_t len)
{
    E53_IIC_Msg msg[1];
    (void)memset_s(msg, sizeof(msg), 0, sizeof(msg));
    msg[0].addr = addr;
    msg[0].buf = data;
    msg[0].len = len;
    msg[0].flags = 0; //写入模式
    if (E53_IICTransmit(msg, 1) != E53_Ok)
    {
        HDF_LOGE("i2c write failed");
        return -1;
    }
    return 0;
}

E53_Status E53_IICRead(uint32_t addr, uint8_t *data, uint32_t len)
{
    E53_IIC_Msg msg;
    msg.addr = addr;
    msg.buf = data;
    msg.len = len;
    msg.flags = E53_I2C_FLAG_READ;
    if (E53_IICTransmit(&msg, 1) != E53_Ok)
    {
        HDF_LOGE("i2c read err");
        return -1;
    }
    return 0;
}

int32_t My_I2C_DriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    int ret;
    char *replay_buf;
    // char* read;
    HDF_LOGE("E53 driver dispatch");
    if (client == NULL || client->device == NULL)
    {
        HDF_LOGE("E53 driver device is NULL");
        return HDF_ERR_INVALID_OBJECT;
    }
    switch (cmdCode)
    {
    case 0:
        E53_IICOpen();
        break;
    default:
        return HDF_FAILURE;
    }
    return HDF_SUCCESS;
}

//驱动对外提供的服务能力，将相关的服务接口绑定到HDF框架
static int32_t My_I2C_DriverBind(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("e53 driver bind failed!");
        return HDF_ERR_INVALID_OBJECT;
    }
    static struct IDeviceIoService e53Driver = {
        .Dispatch = My_I2C_DriverDispatch,
    };
    deviceObject->service = (struct IDeviceIoService *)(&e53Driver);
    HDF_LOGD("E53 driver bind success");
    return HDF_SUCCESS;
}

static int32_t My_I2C_DriverInit(struct HdfDeviceObject *device)
{
    return HDF_SUCCESS;
}

// 驱动资源释放的接口
void My_I2C_DriverRelease(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("Led driver release failed!");
        return;
    }
    HDF_LOGD("Led driver release success");
    return;
}

// 定义驱动入口的对象，必须为HdfDriverEntry（在hdf_device_desc.h中定义）类型的全局变量
struct HdfDriverEntry My_I2C_IA1DriverEntry = {
    .moduleVersion = 1,
    .moduleName = "My_I2C_IA1",
    .Bind = My_I2C_DriverBind,
    .Init = My_I2C_DriverInit,
    .Release = My_I2C_DriverRelease,
};

// 调用HDF_INIT将驱动入口注册到HDF框架中
HDF_INIT(My_I2C_IA1DriverEntry);
